﻿using Apewer.Models;
using System;
using System.Collections.Generic;
using System.Text;
// using System.Threading.Tasks;
using System.IO;
using Apewer.Internals.Interop;

#if NET40_OR_GREATER
using System.Speech.Synthesis;
#endif

namespace Apewer
{

    /// <summary>音频实用工具。</summary>
    public sealed class AudioUtility
    {

        private AudioUtility() { }

        #region WAVE 校验。

        private static int mmioFOURCC(char ch0, char ch1, char ch2, char ch3)
        {
            int num = 0;
            num |= ch0;
            num |= (int)((uint)ch1 << 8);
            num |= (int)((uint)ch2 << 16);
            return num | (int)((uint)ch3 << 24);
        }

        private static int BytesToInt(byte ch0, byte ch1, byte ch2, byte ch3)
        {
            return mmioFOURCC((char)ch3, (char)ch2, (char)ch1, (char)ch0);
        }

        private static short BytesToInt16(byte ch0, byte ch1)
        {
            int num = ch1 | ch0 << 8;
            return (short)num;
        }

        /// <summary>检查字节数组是 WAVE。</summary>
        public static bool IsWave(params byte[] data)
        {
            if (data == null || data.LongLength < 1L) return false;

            int num = 0;
            short num2 = -1;
            bool flag = false;
            if (data.Length < 12) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
            if (data[0] == 82 && data[1] == 73 && data[2] == 70 && data[3] == 70)
            {
                if (data[8] == 87 && data[9] == 65 && data[10] == 86 && data[11] == 69)
                {
                    num = 12;
                    int num3 = data.Length;
                    while (!flag && num < num3 - 8)
                    {
                        if (data[num] == 102 && data[num + 1] == 109 && data[num + 2] == 116 && data[num + 3] == 32)
                        {
                            flag = true;
                            int num4 = BytesToInt(data[num + 7], data[num + 6], data[num + 5], data[num + 4]);
                            int num5 = 16;
                            if (num4 != num5)
                            {
                                int num6 = 18;
                                if (num3 < num + 8 + num6 - 1) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
                                short num7 = BytesToInt16(data[num + 8 + num6 - 1], data[num + 8 + num6 - 2]);
                                if (num7 + num6 != num4) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
                            }
                            if (num3 < num + 9) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
                            num2 = BytesToInt16(data[num + 9], data[num + 8]);
                            num += num4 + 8;
                        }
                        else
                        {
                            num += 8 + BytesToInt(data[num + 7], data[num + 6], data[num + 5], data[num + 4]);
                        }
                    }
                    if (!flag) return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
                    if (num2 == 1) return true;
                    if (num2 == 2) return true;
                    if (num2 == 3) return true;
                    return false; // throw new InvalidOperationException(SR.GetString("SoundAPIFormatNotSupported"));
                }
                return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
            }
            return false; // throw new InvalidOperationException(SR.GetString("SoundAPIInvalidWaveHeader"));
        }

        #endregion

        #region WinMM 控制。

        /// <summary>WinMM：播放音频。</summary>
        /// <param name="wave">波形数据。</param>
        /// <param name="loop">循环播放。</param>
        public static void Play(byte[] wave, bool loop = false)
        {
            if (wave == null || wave.LongLength == 0) return;

            int flag = loop ? 9 : 1;
            try { WinMM.PlaySound(wave, IntPtr.Zero, 6 | flag); } catch { }
        }

        /// <summary>WinMM：停止播放。</summary>
        public static void Stop()
        {
            try { WinMM.PlaySound(null as string, IntPtr.Zero, 64); } catch { }
        }

        private static void MessageBeep(int type)
        {
            try { User32.MessageBeep(type); } catch { }
        }

        /// <summary>播放系统声音。</summary>
        public static void Asterisk() => MessageBeep(64);

        /// <summary>播放系统声音。</summary>
        public static void Beep() => MessageBeep(0);

        /// <summary>播放系统声音。</summary>
        public static void Exclamation() => MessageBeep(48);

        /// <summary>播放系统声音。</summary>
        public static void Hand() => MessageBeep(16);

        /// <summary>播放系统声音。</summary>
        public static void Question() => MessageBeep(32);

        #endregion

#if NET40_OR_GREATER

        /// <summary>列举所有 Speech Voices 的 Name。 </summary>
        public static List<string> ListVoices()
        {
            var list = new List<string>();
            using (var synthesizer = new SpeechSynthesizer())
            {
                var installed = synthesizer.GetInstalledVoices();
                foreach (var voice in installed)
                {
                    list.Add(voice.VoiceInfo.Name);
                }
            }
            return list;
        }

        /// <summary>获取 Voice 信息。</summary>
        public static VoiceInfo GetVoice(string name)
        {
            if (string.IsNullOrEmpty(name)) return null;
            using (var synthesizer = new SpeechSynthesizer())
            {
                var installed = synthesizer.GetInstalledVoices();
                foreach (var voice in installed)
                {
                    if (voice.VoiceInfo.Name == name) return voice.VoiceInfo;
                }
            }
            return null;
        }

        /// <summary>讲述文本，默认为异步执行。</summary>
        public static void Speak(string text, string voice = null, bool async = true)
        {
            if (string.IsNullOrEmpty(text)) return;

            if (async)
            {
                var wave = Render(text, voice);
                Play(wave);
            }
            else
            {
                using (var synthesizer = new SpeechSynthesizer())
                {
                    try
                    {
                        if (!string.IsNullOrEmpty(voice)) synthesizer.SelectVoice(voice);
                        synthesizer.Speak(text);
                    }
                    catch { }
                }
            }
        }

        /// <summary>渲染为音频数据。</summary>
        public static byte[] Render(string text, string voice = null)
        {
            if (string.IsNullOrEmpty(text)) return null;
            using (var memory = new MemoryStream())
            {
                using (var synthesizer = new SpeechSynthesizer())
                {
                    try
                    {
                        if (!string.IsNullOrEmpty(voice)) synthesizer.SelectVoice(voice);
                        synthesizer.SetOutputToWaveStream(memory);
                        synthesizer.Speak(text);
                    }
                    catch { }
                }
                var bytes = memory.ToArray();
                return bytes;
            }
        }

#endif

    }

}

